#include <behaviortree_cpp_v3/bt_factory.h>
#include <iostream>
#include <stdio.h>
using namespace std;

class calculateBlockGlobal : public BT::SyncActionNode
{
public:
    calculateBlockGlobal(const std::string& name, const BT::NodeConfiguration& config)
        : BT::SyncActionNode(name, config)
    {
    }

    // You must override the virtual function tick()
    BT::NodeStatus tick() override
    {
        int x, y, result;
        getInput<int>("cal_x", x); // 获取输入变量
        getInput<int>("cal_y", y);
        result = x + y;
        setOutput<int>("result", result); // 设置输出变量
        printf("cal_x + cal_y = %d + %d = %d\n", x, y, result);
        return BT::NodeStatus::SUCCESS;
    }

    // It is mandatory to define this static method.
    static BT::PortsList providedPorts()
    {
        return{
            BT::InputPort<int>("cal_x"),
            BT::InputPort<int>("cal_y"),
            BT::OutputPort<int>("result"),
        };
    }
};

class getCalculateResult : public BT::SyncActionNode
{
public:
    getCalculateResult(const std::string& name, const BT::NodeConfiguration& config)
        : BT::SyncActionNode(name, config)
    {
    }

    // You must override the virtual function tick()
    BT::NodeStatus tick() override
    {
        int result;
        getInput<int>("result", result); // 获取输入变量
        cout << this->name() << "result: " << result << endl;
        return BT::NodeStatus::SUCCESS;
    }

    // It is mandatory to define this static method.
    static BT::PortsList providedPorts()
    {
        return{
            BT::InputPort<int>("result"),
        };
    }
};

// 带参数的节点, 输入变量为message, 全局变量
static const char* xml_text = R"(
 <root main_tree_to_execute = "MainTree" >

     <BehaviorTree ID="MainTree">
        <Sequence name="root">
            <calculateBlockGlobal cal_x="2" cal_y="3" result="{cal_result}"/>
            <getCalculateResult result="{cal_result}"/>
        </Sequence>
     </BehaviorTree>

 </root>
 )";

int main()
{
    BT::BehaviorTreeFactory factory;

    // 注册节点类型
    factory.registerNodeType<calculateBlockGlobal>("calculateBlockGlobal");
    factory.registerNodeType<getCalculateResult>("getCalculateResult");

    // 从xml 加载行为树
    BT::Tree tree = factory.createTreeFromText(xml_text);

    // 打印行为树结构到标准输出
    cout << "=== 行为树结构 ===" << endl;
    printTreeRecursively(tree.rootNode());

    // 执行行为树
    tree.tickRootWhileRunning();

    return 0;
}

/* 运行结果:
=== 行为树结构 ===
----------------
root
   calculateBlockGlobal
   getCalculateResult
----------------
cal_x + cal_y = 2 + 3 = 5
getCalculateResultresult: 5

*/